package com.leyou.auth.service;

import com.leyou.auth.config.JwtProperties;
import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.auth.utils.RsaUtils;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.CookieUtils;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.UserDTO;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PrivateKey;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class AuthService {

    @Autowired
    private UserClient userClient;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void login(String username, String password, HttpServletResponse response) {
//        1、根据用户名和密码远程调用用户中心微服务
        UserDTO userDTO = userClient.queryUserByUsernameAndPassword(username, password);
//        2、获取的UserDTO转成UserInfo
        UserInfo userInfo = BeanHelper.copyProperties(userDTO, UserInfo.class);
//        3、加密
        generateTokenAndSetCookie(response, userInfo);
    }

    public UserInfo verify(HttpServletRequest request, HttpServletResponse response) {
        try {
//         1、从cookie中获取token
            String token = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());
//         2、解析token  使用的公钥  //         3、返回载荷 PayLoad
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey(), UserInfo.class);
//            判断这个payload的id是否在redis的黑名单中
            if(redisTemplate.hasKey(payload.getId())){
                return null;  //意味着 这个token已经被退出了 ，加入到了redis的黑名单中
            }
//            判断token是否即将过时（是否低于15分钟）
            Date expirationTime = payload.getExpiration();  // 什么时候过期
//            expirationTime - 当前时间 <= 15分钟    //重新生成一个token
//            expirationTime - 15分钟 <= 当前时间     //重新生成一个token
//         3、从payLoad中获取UserInfo
            UserInfo userInfo = payload.getUserInfo();
            if(new DateTime(expirationTime).minusMinutes(jwtProperties.getUser().getMinRefreshInterval()).isBeforeNow()){
//                重新生成一个token,还需要把token放入到cookie中
//              加密
                generateTokenAndSetCookie(response, userInfo);
            }
            return userInfo;
        } catch (Exception e) {
            return null;
        }
    }

    private void generateTokenAndSetCookie(HttpServletResponse response, UserInfo userInfo) {
        String token = JwtUtils.generateTokenExpireInMinutes(userInfo, jwtProperties.getPrivateKey(), jwtProperties.getUser().getExpire());
//       把加密后的token字符串放入到cookie中
        CookieUtils.newCookieBuilder().name(jwtProperties.getUser().getCookieName())
                .value(token)
                .domain(jwtProperties.getUser().getCookieDomain())
                .httpOnly(true)    //禁用js操作cookie信息 目的：为了防止xss攻击
                .response(response)
                .maxAge(60*60*24*7)
                .build();
    }


    public void logout(HttpServletRequest request, HttpServletResponse response) {
        String token = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());
//         2、解析token  使用的公钥  //         3、返回载荷 PayLoad
        Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey(), UserInfo.class);
//        把token标记成已失效
//        把在redis中做一个黑名单，就是把退出的token在redis中做一个标记
        String payloadId = payload.getId();
        long l = payload.getExpiration().getTime() - new Date().getTime();  // token还有多长时间失效
        redisTemplate.boundValueOps(payloadId).set("",l, TimeUnit.MILLISECONDS);  //在redis中存放多长时间 30分钟
//        删除cookie
        CookieUtils.deleteCookie(jwtProperties.getUser().getCookieName(),jwtProperties.getUser().getCookieDomain(),response);

    }
}
